package com.istock.union.security;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.istock.base.enumration.Enums;
import com.istock.base.serializer.JsonSerializer;
import com.istock.base.serializer.json.JsonSerializerFactory;
import com.istock.union.user.client.SSOClientUtils;
import com.istock.union.user.model.OperLog;
import com.istock.union.user.model.OperLogInfo;
import com.istock.union.user.model.SSOUser;
import com.istock.union.user.service.AschTaskService;
import com.istock.union.user.utils.WebCommonUtils;

@Aspect
public class OperLogAspect {

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private AschTaskService aschTaskService;
	
	@AfterReturning(value="within(@org.springframework.stereotype.Controller *) && @annotation(com.istock.union.user.model.OperLog)")
	public void recordReturn(JoinPoint jp) throws Throwable{
		recordLog(jp  , null);
	}
	
	@AfterThrowing(value="within(@org.springframework.stereotype.Controller *) && @annotation(com.istock.union.user.model.OperLog)" , throwing = "ex")
	public void recordThrow(JoinPoint jp , Throwable ex) throws Throwable{
		recordLog(jp , ex);
	}
	
	private void recordLog(JoinPoint jp , Throwable ex) {
		try {
			MethodSignature signature = (MethodSignature)jp.getSignature();
			Method method = signature.getMethod();
			OperLog operLog = method.getAnnotation(OperLog.class);
			OperLogInfo logInfo = new OperLogInfo();
			logInfo.setMenuName(operLog.menuName());
			logInfo.setFunctionName(operLog.functionName());
			logInfo.setOperTime(new Date());
			logInfo.setMethod(jp.getTarget().getClass().getCanonicalName()+":"+method.getName());
			
//			String targetClassName = jp.getTarget().getClass().getSimpleName();
//			String methodName = jp.getSignature().getName();
			
			HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
			if(request != null) {
				logInfo.setOperUrl(WebCommonUtils.findAccessPath(request));
				logInfo.setOperIp(WebCommonUtils.findRemoteAddr(request));
				if(operLog.saveRequestData()) {
					Map paramMap = request.getParameterMap();
					if(paramMap != null) {
						JsonSerializer serializer = JsonSerializerFactory.findSerializer();
						logInfo.setOperParam(StringUtils.substring(serializer.serialize(paramMap),0,1000));
//						logInfo.setOperParam(StringUtils.substring(JSON.toJSONString(paramMap),0,1000));
					}
				}
			}
			
			SSOUser ssoUser = SSOClientUtils.getInstance().findCurrentUser();
			if(ssoUser != null) {
				logInfo.setOperName(ssoUser.getUserName());
				if(ssoUser.getCurrentDept() != null) {
					logInfo.setDeptCode(ssoUser.getCurrentDept().getDeptCode());
				}
			}
			
			if(ex != null) {
				logInfo.setStatus(Enums.getInstance().getEnumsValueByCode("COMMON_STATUS", "COMMON_STATUS_F"));
				logInfo.setErrorMsg(ex.getMessage());
			}else {
				logInfo.setStatus(Enums.getInstance().getEnumsValueByCode("COMMON_STATUS", "COMMON_STATUS_S"));
			}
			
			aschTaskService.operateRecord(logInfo);
		}catch(Exception e) {
			logger.error("throw exception when record operLog" ,  e);
		}
	}
	
	private OperLog findOperLog(JoinPoint jp) {
		MethodSignature signature = (MethodSignature)jp.getSignature();
		Method method = signature.getMethod();
		if(method != null) {
			return method.getAnnotation(OperLog.class);
		}
		return null;
	}
}
